/**
 * 
 */
package com.toncen.samepms.common;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;

import com.toncen.samepms.basic.dao.ProcessLogDao;
import com.toncen.samepms.basic.dao.UserDao;
import com.toncen.samepms.basic.domain.Organization;
import com.toncen.samepms.basic.domain.ProcessLog;
import com.toncen.samepms.basic.domain.User;
import com.toncen.samepms.interceptor.Begin;
import com.toncen.samepms.interceptor.End;
import com.toncen.samepms.interceptor.In;
import com.toncen.samepms.interceptor.Out;
import com.toncen.samepms.interceptor.Transaction;
import com.toncen.samepms.system.dao.CodeDao;
import com.toncen.samepms.system.dao.CodeItemDao;
import com.toncen.samepms.system.dao.ConfigurationDao;
import com.toncen.samepms.system.dao.RoleBlockRightDao;
import com.toncen.samepms.system.domain.Code;
import com.toncen.samepms.system.domain.CodeItem;
import com.toncen.samepms.system.domain.Role;
import com.toncen.samepms.util.RandomNumUtil;
import com.toncen.samepms.util.RoleUtils;
import com.toncen.samepms.util.SQLUtils;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
import com.sky.common.clone.CloneUtils;
import com.sky.common.date.DateTools;
import com.sky.common.lang.ClassUtils;
import com.sky.common.properties.PropertiesUtils;
import com.sky.common.string.StringUtils;
import com.sky.simple.engine.IWorkflowParticipator;
import com.sky.simple.engine.IWorkflowProcessable;
import com.sky.simple.engine.IWorkflowRuntimeContext;
import com.sky.simple.engine.SimpleWorkflow;
import com.sky.simple.model.Activity;

/**
 * 描述：Action基类
 * 
 * @author tch
 */
public abstract class AbstractAction<M extends IDomain> extends ActionSupport implements Preparable, IWorkflowRuntimeContext {
	/**
	 * 当前用户拥有的功能权限在session中的名称
	 */
	public final static String MODULE_SESSION_ATTRIBUTE = "modules";

	/**
	 * 当前用户验证码在session中的名称
	 */
	public final static String VERIFICATION_SESSION_ATTRIBUTE = "verification";

	/**
	 * 当前用户主题皮肤设置在session中的名称
	 */
	public final static String SKIN_CONFIGURATION_SESSION_ATTRIBUTE = "skinCon";

	/**
	 * 数据过滤分隔符
	 */
	public final static String FILTER_SEPARATOR = ",";

	/**
	 * 批量操作最大数量
	 */
	public final static int SAVES_MAX_SIZE = 20;

	/**
	 * 
	 */
	protected Log logger = LogFactory.getLog(this.getClass());

	/**
	 * 当前action操作的主domain的class类型
	 */
	private Class domainClass;

	/**
	 * 当前action操作的主domain
	 */
	@In
	@Out
	private M domain;

	/**
	 * 当前action批量操作的主domain的id
	 */
	@In
	@Out
	private long[] domainIds;

	/**
	 * 当前action批量操作的主domain集合
	 */
	@In
	@Out
	private M[] domains;

	/**
	 * 当前位置索引
	 */
	@In
	@Out
	private String index;

	/**
	 * 当前操作名称
	 */
	@In
	@Out
	private String operate;

	/**
	 * 是否只读
	 */
	@In
	@Out
	private boolean readonly;

	/**
	 * 是否禁用
	 */
	@In
	@Out
	private boolean disabled;

	/**
	 * 数据过滤类型
	 */
	@In
	@Out
	private String filterType;

	/**
	 * 数据过滤名字
	 */
	@In
	@Out
	private String filterName;

	/**
	 * 复制字段名，多个字段之间用英文逗号分割
	 */
	@In
	@Out
	private String copyName;

	/**
	 * 验证码
	 */
	private String verification;

	/**
	 * 验证码图片
	 */
	private ByteArrayInputStream verificationInputStream;

	/**
	 * 流程标识
	 */
	@In
	@Out
	private String processId;

	/**
	 * 流程下一个活动标识
	 */
	private long nextActivityId;

	/**
	 * 流程上一个参与者
	 */
	private IWorkflowParticipator lastParticipator;

	/**
	 * 流程操作日志
	 */
	@In
	@Out
	private ProcessLog processLog;

	/**
	 * 
	 */
	private String tip;

	/**
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * 
	 */
	@SuppressWarnings("unchecked")
	public AbstractAction() throws Exception {
		domainClass = ClassUtils.getParameterizedType(this.getClass(), 0);
		domain = (M) domainClass.newInstance();
		domains = (M[]) Array.newInstance(domainClass, SAVES_MAX_SIZE);
		M d;
		for (int i = 0; i < domains.length; i++) {
			d = (M) domainClass.newInstance();
			domains[i] = d;
		}
		if (domain instanceof IWorkflowProcessable) {// 流程对象，则实例化流程日志
			processLog = new ProcessLog();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.opensymphony.xwork2.Preparable#prepare()
	 */
	public void prepare() throws Exception {
		logger.debug("执行【prepare】...");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.opensymphony.xwork2.ActionSupport#validate()
	 */
	public void validate() {
		super.validate();
		logger.debug("执行【validate】...");
	}

	/**
	 * 列表初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoList() throws Exception {
		logger.debug("执行【prepareOnDoList】...");
		this.setOperate("查看");
		if (!StringUtils.isEmpty(getFilterType()) && !StringUtils.isEmpty(getFilterName())) {
			if(getFilterType().equals(StringUtils.getSecString(getFilterType()))&&getFilterName().equals(StringUtils.getSecString(getFilterName())))
			{
				String[] filterTypes = StringUtils.getSecString(getFilterType()).split(FILTER_SEPARATOR, -1);//
				String[] filterNames =  StringUtils.getSecString(getFilterName()).split(FILTER_SEPARATOR, -1);//
				if (filterTypes.length != filterNames.length) {
					throw new Exception("数据过滤类型【" + getFilterType() + "】(" + filterTypes.length + ")与数据过滤名字【" + getFilterName() + "】(" + filterNames.length
							+ ")长度不一致，请与系统管理员联系！");
				}
				for (int i = 0; i < filterTypes.length; i++) {
					if (!StringUtils.isEmpty(filterTypes[i]) && !StringUtils.isEmpty(filterNames[i])) {
						ServletActionContext.getRequest().setAttribute(filterNames[i], getPermissions(filterTypes[i], getCurrentUser()));
					}
				}
			}
			else
			{
				throw new Exception("提交数据中包含有非法字段！");
			}
		}
	}

	/**
	 * 列表验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoList() throws Exception {
		logger.debug("执行【validateOnDoList】...");
	}

	/**
	 * 列表
	 * 
	 * @return
	 * @throws Exception
	 */
	@End
	public String onDoList() throws Exception {
		logger.debug("执行【onDoList】...");
		return SUCCESS;
	}

	/**
	 * 新增初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoNew() throws Exception {
		logger.debug("执行【prepareOnDoNew】...");
		this.setOperate("新增");
	}

	/**
	 * 新增验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoNew() throws Exception {
		logger.debug("执行【validateOnDoNew】...");
	}

	/**
	 * 新增
	 * 
	 * @return
	 * @throws Exception
	 */
	@Begin
	public String onDoNew() throws Exception {
		logger.debug("执行【onDoNew】...");
		return SUCCESS;
	}

	/**
	 * 修改初始化
	 * 
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public void prepareOnDoEdit() throws Exception {
		logger.debug("执行【prepareOnDoEdit】...");
		this.setOperate("修改");
		setDomain(load(getDomain().getId()));
	}

	/**
	 * 修改验证
	 * 
	 * @throws Exception
	 */
	public void validateDoEdit() throws Exception {
		super.validate();
		logger.debug("执行【validateDoEdit】...");
	}

	/**
	 * 修改
	 * 
	 * @return
	 * @throws Exception
	 */
	@Begin
	public String onDoEdit() throws Exception {
		logger.debug("执行【onDoEdit】...");
		return SUCCESS;
	}

	/**
	 * 查看初始化
	 * 
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public void prepareOnDoView() throws Exception {
		logger.debug("执行【prepareOnDoView】...");
		this.setOperate("查看");
		setDomain(load(getDomain().getId()));
	}

	/**
	 * 查看验证
	 * 
	 * @throws Exception
	 */
	public void validateDoView() throws Exception {
		super.validate();
		logger.debug("执行【validateDoView】...");
	}

	/**
	 * 查看
	 * 
	 * @return
	 * @throws Exception
	 */
	@Begin
	public String onDoView() throws Exception {
		logger.debug("执行【onDoView】...");
		this.setReadonly(true);
		return SUCCESS;
	}

	/**
	 * 单个保存初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoSave() throws Exception {
		logger.debug("执行【prepareOnDoSave】...");
	}

	/**
	 * 单个保存验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoSave() throws Exception {
		super.validate();
		logger.debug("执行【validateOnDoSave】...");
	}

	/**
	 * 单个保存
	 * 
	 * @return
	 * @throws Exception
	 */
	@End
	@Transaction
	@SuppressWarnings("unchecked")
	public String onDoSave() throws Exception {
		logger.debug("执行【onDoSave】....");
		Activity activity = process(domain);
		save(getDomain());
		logprocess(activity, domain);
		return SUCCESS;
	}

	/**
	 * 批量保存初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoSaves() throws Exception {
		logger.debug("执行【prepareOnDoSaves】...");
		M temp;
		M d;
		for (int i = 0; i < getDomains().length; i++) {// 加载数据库中的数据
			d = getDomains()[i];
			if (d != null && d.isSaved()) {
				temp = find(d.getId());
				if (temp != null) {
					d = temp;
					getDomains()[i] = temp;
				}
			}
		}
	}

	/**
	 * 批量保存验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoSaves() throws Exception {
		super.validate();
		logger.debug("执行【validateOnDoSaves】...");
	}

	/**
	 * 批量保存
	 * 
	 * @return
	 * @throws Exception
	 */
	@End
	@Transaction
	@SuppressWarnings("unchecked")
	public String onDoSaves() throws Exception {
		logger.debug("执行【onDoSaves】....");
		for (M d : getDomains()) {
			if (d != null && d.isSaved()) {
				save(d);
			}
		}
		return SUCCESS;
	}

	/**
	 * 单个删除初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoDelete() throws Exception {
		logger.debug("执行【prepareOnDoDelete】...");
	}

	/**
	 * 单个删除验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoDelete() throws Exception {
		super.validate();
		logger.debug("执行【validateOnDoDelete】...");
	}

	/**
	 * 单个删除
	 * 
	 * @return
	 * @throws Exception
	 */
	@End
	@Transaction
	@SuppressWarnings("unchecked")
	public String onDoDelete() throws Exception {
		logger.debug("执行【onDoDelete】....");
		delete(getDomain().getId());
		return SUCCESS;
	}

	/**
	 * 批量删除初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoDeletes() throws Exception {
		logger.debug("执行【prepareOnDoDeletes】...");
	}

	/**
	 * 批量删除验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoDeletes() throws Exception {
		super.validate();
		logger.debug("执行【validateOnDoDeletes】...");
	}

	/**
	 * 批量删除
	 * 
	 * @return
	 * @throws Exception
	 */
	@End
	@Transaction
	public String onDoDeletes() throws Exception {
		logger.debug("执行【onDoDeletes】....");
		if (getDomainIds() != null) {
			for (long id : getDomainIds()) {
				delete(id);
			}
		}
		return SUCCESS;
	}

	/**
	 * 单个改变状态初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoChange() throws Exception {
		logger.debug("执行【prepareOnDoChange】...");
	}

	/**
	 * 单个改变状态验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoChange() throws Exception {
		super.validate();
		logger.debug("执行【validateOnDoChange】...");
	}

	/**
	 * 单个改变状态
	 * 
	 * @return
	 * @throws Exception
	 */
	@End
	@Transaction
	@SuppressWarnings("unchecked")
	public String onDoChange() throws Exception {
		logger.debug("执行【onDoChange】....");
		save(getDomain());
		return SUCCESS;
	}

	/**
	 * 批量改变状态初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoChanges() throws Exception {
		logger.debug("执行【prepareOnDoChanges】...");
	}

	/**
	 * 批量改变状态验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoChanges() throws Exception {
		super.validate();
		logger.debug("执行【validateOnDoChanges】...");
	}

	/**
	 * 批量改变状态
	 * 
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@End
	@Transaction
	public String onDoChanges() throws Exception {
		logger.debug("执行【onDoChanges】....");
		if (getDomainIds() != null) {
			M domain;
			for (long id : getDomainIds()) {
				domain = load(id);
				domain.setState(getDomain().getState());
				save(domain);
			}
		}
		return SUCCESS;
	}

	/**
	 * 单个复制初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoCopy() throws Exception {
		logger.debug("执行【prepareOnDoCopy】...");
	}

	/**
	 * 单个复制验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoCopy() throws Exception {
		super.validate();
		logger.debug("执行【validateOnDoCopy】...");
	}

	/**
	 * 单个复制
	 * 
	 * @return
	 * @throws Exception
	 */
	@End
	@Transaction
	@SuppressWarnings( { "unchecked", "static-access" })
	public String onDoCopy() throws Exception {
		logger.debug("执行【onDoCopy】....");
		copyDomain(getDomain(), getCopyName());
		save(getDomain());
		return SUCCESS;
	}

	/**
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws NoSuchMethodException
	 */
	protected void copyDomain(IDomain domain, String copyName) throws Exception {
		domain.setId(getPrimaryID());
		if (!StringUtils.isEmpty(copyName)) {
			String[] copyNames = copyName.split(",", -1);
			String copy;
			for (int i = 1; i <= copyNames.length; i++) {
				copy = copyNames[i - 1];
				if (!StringUtils.isEmpty(copy)) {
					BeanUtils.setProperty(domain, copy, "复制[" + i + "]：" + BeanUtils.getProperty(domain, copy));
				}
			}
		}
	}

	/**
	 * 批量复制初始化
	 * 
	 * @throws Exception
	 */
	public void prepareOnDoCopys() throws Exception {
		logger.debug("执行【prepareOnDoCopys】...");
	}

	/**
	 * 批量复制验证
	 * 
	 * @throws Exception
	 */
	public void validateOnDoCopys() throws Exception {
		super.validate();
		logger.debug("执行【validateOnDoCopys】...");
	}

	/**
	 * 批量复制
	 * 
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings( { "unchecked", "static-access" })
	@End
	@Transaction
	public String onDoCopys() throws Exception {
		logger.debug("执行【onDoCopys】....");
		M domain;
		for (long id : getDomainIds()) {
			domain = load(id);
			copyDomain(domain, getCopyName());
			save(domain);
		}
		return SUCCESS;
	}

	/**
	 * @return the domain
	 */
	public M getDomain() {
		return domain;
	}

	/**
	 * @param domain
	 *            the domain to set
	 */
	public void setDomain(M domain) {
		this.domain = domain;
	}

	/**
	 * @return the domainClass
	 */
	public Class getDomainClass() {
		return domainClass;
	}

	/**
	 * @return the domainClass
	 */
	public Class getActionClass() {
		return this.getClass();
	}

	/**
	 * @return the index
	 */
	public String getIndex() {
		return index;
	}

	/**
	 * @param index
	 *            the index to set
	 */
	public void setIndex(String index) {
		this.index = index;
	}

	/**
	 * @return the operate
	 */
	public String getOperate() {
		return operate;
	}

	/**
	 * @param operate
	 *            the operate to set
	 */
	public void setOperate(String operate) {
		this.operate = operate;
	}

	/**
	 * @return the readonly
	 */
	public boolean isReadonly() {
		return readonly;
	}

	/**
	 * @param readonly
	 *            the readonly to set
	 */
	public void setReadonly(boolean readonly) {
		this.readonly = readonly;
	}

	/**
	 * @return the disabled
	 */
	public boolean isDisabled() {
		return disabled;
	}

	/**
	 * @param disabled
	 *            the disabled to set
	 */
	public void setDisabled(boolean disabled) {
		this.disabled = disabled;
	}

	/**
	 * @return the domainIds
	 */
	public long[] getDomainIds() {
		return domainIds;
	}

	/**
	 * @param domainIds
	 *            the domainIds to set
	 */
	public void setDomainIds(long[] domainIds) {
		this.domainIds = domainIds;
	}

	/**
	 * @return the domains
	 */
	public M[] getDomains() {
		return domains;
	}

	/**
	 * @param domains
	 *            the domains to set
	 */
	public void setDomains(M[] domains) {
		this.domains = domains;
	}

	/**
	 * @return the filteName
	 */
	public String getFilterName() {
		return filterName;
	}

	/**
	 * @param filteName
	 *            the filteName to set
	 */
	public void setFilterName(String filteName) {
		this.filterName = filteName;
	}

	/**
	 * @return the filteType
	 */
	public String getFilterType() {
		return filterType;
	}

	/**
	 * @param filteType
	 *            the filteType to set
	 */
	public void setFilterType(String filteType) {
		this.filterType = filteType;
	}

	/**
	 * @return the copyName
	 */
	public String getCopyName() {
		return copyName;
	}

	/**
	 * @param copyName
	 *            the copyName to set
	 */
	public void setCopyName(String copyName) {
		this.copyName = copyName;
	}

	/**
	 * 删除指定id的对象
	 * 
	 * @param domain
	 * @throws Exception
	 */
	public abstract void delete(long domainId) throws Exception;

	/**
	 * 保存对象
	 * 
	 * @param domain
	 * @throws Exception
	 */
	public abstract void save(M domain) throws Exception;

	/**
	 * 加载指定id的对象
	 * 
	 * @param domain
	 * @return
	 * @throws Exception
	 */
	public abstract M load(long domainId) throws Exception;

	/**
	 * 查询指定id的对象
	 * 
	 * @param domainId
	 * @return
	 * @throws Exception
	 */
	public abstract M find(long domainId) throws Exception;

	/**
	 * 获取指定名称的编码
	 * 
	 * @param code
	 * @return
	 * @throws Exception
	 */
	public List<CodeItem> getCodeItemList(String code) throws Exception {
		CodeDao codeDao = new CodeDao();
		Code c = codeDao.getByCode(code);
		if (c == null) {
			// xl 2012-05-29 如果编码不存在则添加
			c = new Code();
			c.setDescription("自动添加[" + DateTools.getDateTime() + "]");
			c.setCode(code);
			c.setState(1);
			c.setSequence(0);
			codeDao.save(c);
			// throw new Exception("编码【" + code + "】不存在，请与系统管理员联系！");
		}
		return ((Code) CloneUtils.deepClone(c)).getCodeItemList();
	}

	/**
	 * create:xl create date:2012-8-8上午11:04:12 方法描述： 获取指定名称的编码 同时排出获取指定的值
	 */
	@SuppressWarnings("unchecked")
	public List<CodeItem> getCodeItemList(String code, String selvalue) throws Exception {
		CodeItemDao codeItemDao = new CodeItemDao();
		selvalue = "'" + selvalue.replace(",", "','") + "'";
		String sqlStr = "select a.* from system_code_item a" + " left join  system_code b on a.code_id= b.id" + " where b.code='" + code
				+ "' and a.value  in (" + selvalue + ") order by a.SEQUENCE";
		List<CodeItem> list = new ArrayList<CodeItem>();
		list = codeItemDao.getCodeItem(sqlStr);
		return list;
	}

	/**
	 * 根据编码名称和编码值获取正在使用的编码明细
	 * 
	 * @param code
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public String getCodeItem(String code, String value) throws Exception {
		List<CodeItem> codeItemList = getCodeItemList(code);
		for (CodeItem codeItem : codeItemList) {
			if (codeItem.getValue().equals(value)) {
				return codeItem.getName();
			}
		}
		return "";
	}

	/**
	 * 根据系统配置名称获取配置的值
	 * 
	 * @param name
	 * @return
	 */
	public String getConfigValue(String name) throws Exception {
		return new ConfigurationDao().getValueByName(name);
	}

	/**
	 * 根据(角色+系统配置名称)获取配置的值
	 * 
	 * 
	 * 
	 * @param name
	 * @return
	 */
	public String getConfigValueForRole(String name) throws Exception {
		User user = getCurrentUser();
		String key = name;
		for (Role role : user.getRoles()) {
			key += role.getId();
			break;
		}
		return new ConfigurationDao().getValueByName(key);
	}

	/**
	 * 获取当前用户
	 * 
	 * @return
	 * @throws Exception
	 */
	public User getCurrentUser() throws Exception {
		User user = (User) ActionContext.getContext().getSession().get(ComitConstant.USER_SESSION_ATTRIBUTE);
		if (user == null) {
			throw new Exception("当前登录用户不存在或者登录超时，请重新登录！");
		}
		// 复制用户
		User userClone = new User();
		PropertyUtils.copyProperties(userClone, user);
		// 复制组织
		Organization organizationClone = new Organization();
		PropertyUtils.copyProperties(organizationClone, user.getOrganization());
		userClone.setOrganization(organizationClone);
		// 复制角色
		List<Role> roleClone = new ArrayList<Role>();
		Role roleC = null;
		for (Role r : user.getRoles()) {
			roleC = new Role();
			PropertyUtils.copyProperties(roleC, r);
			roleClone.add(roleC);
		}
		// PropertyUtils.copyProperties(roleClone, user.getRoles());
		userClone.setRoles(roleClone);
		return userClone;
	}

	/**
	 * 获取当前组织
	 * 
	 * @return
	 * @throws Exception
	 */
	public Organization getCurrentOrganization() throws Exception {
		Organization organization = getCurrentUser().getOrganization();
		if (organization == null) {
			organization = new Organization();
		}
		Organization organizationClone = new Organization();
		PropertyUtils.copyProperties(organizationClone, organization);
		return organizationClone;
	}

	/**
	 * 是否是指定的角色
	 * 
	 * @param role
	 * @return
	 * @throws Exception
	 */
	public boolean isRole(long role) throws Exception {
		return RoleUtils.isRole(getCurrentUser(), role);
	}

	/**
	 * 是否超级管理员
	 * 
	 * @return
	 * @throws Exception
	 */
	public boolean isSuperAdministrator() throws Exception {
		return RoleUtils.isRole(getCurrentUser(), AbstractAccessPermissionProvider.getSuperAdministrator());
	}

	/**
	 * 获取主键
	 * 
	 * @return
	 * @throws Exception
	 */
	public long getPrimaryID() throws Exception {
		return AbstractDao.getPrimaryID();
	}

	/**
	 * 获取当前用户可操作数据权限
	 * 
	 * @param type
	 * @param currentUser
	 * @return
	 * @throws Exception
	 */
	protected String getPermissions(String type, User currentUser) throws Exception {
		List<AbstractDomain> permisionList = getPermissionList(type, currentUser);
		String permisions = SQLUtils.getInSQL(permisionList, "id");
		logger.debug("当前用户【" + currentUser.getName() + "】可操作类型【" + type + "】数据权限【" + permisions + "】...");
		return permisions;
	}

	/**
	 * 获取当前用户可操作数据权限
	 * 
	 * @param type
	 * @param currentUser
	 * @return
	 * @throws Exception
	 */
	protected final List<AbstractDomain> getPermissionList(String type, User currentUser) throws Exception {
		String accessPermissionClass = DefaultAccessPermissionProvider.class.getName();
		try {
			accessPermissionClass = PropertiesUtils.getParameter(AbstractAccessPermissionProvider.FILE_ACCESS_PERMISION,
					AbstractAccessPermissionProvider.KEY_ACCESS_PERMISION_PROVIDER);
		} catch (Exception e) {
			logger.debug("未设置可操作数据权限提供者，系统将使用默认可操作数据权限提供者【" + DefaultAccessPermissionProvider.class.getName() + "】...");
		}
		Object accessPermission = ClassUtils.newInstance(accessPermissionClass);
		if (!(accessPermission instanceof AbstractAccessPermissionProvider)) {
			throw new Exception("可操作数据权限提供者类型【" + accessPermission.getClass().getName() + "】不正确，必须继承【" + AbstractAccessPermissionProvider.class.getName()
					+ "】，请与系统管理员联系!");
		}
		User user = new UserDao<User>().load(currentUser);
		List<AbstractDomain> permisionList = ((AbstractAccessPermissionProvider) accessPermission).getAccessPermissions(this, user, type);
		logger.debug("当前用户【" + user.getName() + "】可操作数据类型【" + type + "】数据权限【" + permisionList + "】...");
		return permisionList;
	}

	/**
	 * create:xl create date:2011-7-11下午03:25:49 包名：com.comit.comm_abstract
	 * 类名：AbstractService.java 方法描述：定义权限 增、删、改、查、编辑下拉框、导入excel、导出excel等操作按钮权限设置
	 * 
	 * @param request
	 * @throws Exception
	 * 
	 */
	@SuppressWarnings("unchecked")
	public HashMap getRight() throws Exception {
		// 根据用户角色设置权限
		String className = getDomainClass().getSimpleName();// 获取domain类名
		String roleId = "";// 角色ID
		User user = getCurrentUser();// 获取当前用户

		// 当前用户所属角色
		if (("").equals(roleId) || "" == roleId) {
			List<Role> roleList = user.getRoles();
			for (Role role : roleList) {
				roleId = roleId + role.getId();
			}
		}

		// 通过角色和模块Domain类名查询操作权限
		RoleBlockRightDao srbrDao = new RoleBlockRightDao();
		Map<String, String> map = new HashMap<String, String>();
		map.put("roleId", roleId);
		map.put("blockNum", className);
		List<HashMap> rightList = srbrDao.getByRoleIdAndBlockNum(map);

		String rightCode = null;
		String rightIsok = null;
		HashMap hashMap = new HashMap();

		// 将查询加过重新组装数据放到hashmap中
		for (HashMap hashmap : rightList) {
			rightCode = String.valueOf(hashmap.get("RIGHT_CODE"));
			rightIsok = String.valueOf(hashmap.get("RIGHT_ISOK"));
			hashMap.put(rightCode, rightIsok);
		}
		return hashMap;
	}

	/**
	 * @return
	 * @throws Exception
	 */
	public String onDoVerificationImage() throws Exception {
		RandomNumUtil randomNumUtil = new RandomNumUtil(4);
		ActionContext.getContext().getSession().remove(VERIFICATION_SESSION_ATTRIBUTE);
		ActionContext.getContext().getSession().put(VERIFICATION_SESSION_ATTRIBUTE, randomNumUtil.getString());// 验证码值放入session中
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);
		ImageIO.write(randomNumUtil.getImage(), "JPEG", imageOut);
		imageOut.close();
		this.verificationInputStream = new ByteArrayInputStream(output.toByteArray());
		return SUCCESS;
	}

	/**
	 * 验证验证码
	 * 
	 * @throws Exception
	 */
	public void validateVerification() throws Exception {
		if (StringUtils.isEmpty(getVerification())) {
			throw new Exception("验证码不能为空，请输入！");
		}
		if (ActionContext.getContext().getSession().get(VERIFICATION_SESSION_ATTRIBUTE) == null
				|| !getVerification().equalsIgnoreCase(ActionContext.getContext().getSession().get(VERIFICATION_SESSION_ATTRIBUTE).toString())) {
			throw new Exception("验证码错误，请重新输入！");
		}
	}

	/**
	 * @return the verification
	 */
	public String getVerification() {
		return verification;
	}

	/**
	 * @param verification
	 *            the verification to set
	 */
	public void setVerification(String verification) {
		this.verification = verification;
	}

	/**
	 * @return the verificationInputStream
	 */
	public ByteArrayInputStream getVerificationInputStream() {
		return verificationInputStream;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.sky.simple.engine.IWorkflowRuntimeContext#getProcessId()
	 */
	public String getProcessId() {
		return processId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.sky.simple.engine.IWorkflowRuntimeContext#setProcessId(java.lang.String)
	 */
	public void setProcessId(String processId) {
		this.processId = processId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.sky.simple.engine.IWorkflowRuntimeContext#getNextActivityId()
	 */
	public long getNextActivityId() {
		return nextActivityId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.sky.simple.engine.IWorkflowRuntimeContext#setNextActivityId(long)
	 */
	public void setNextActivityId(long nextActivityId) {
		this.nextActivityId = nextActivityId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.sky.simple.engine.IWorkflowRuntimeContext#getLastParticipator()
	 */
	public IWorkflowParticipator getLastParticipator() {
		return lastParticipator;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.sky.simple.engine.IWorkflowRuntimeContext#setLastParticipator(com.sky.simple.engine.IWorkflowParticipator)
	 */
	public void setLastParticipator(IWorkflowParticipator lastParticipator) {
		this.lastParticipator = lastParticipator;
	}

	public ProcessLog getProcessLog() {
		return processLog;
	}

	public void setProcessLog(ProcessLog processLog) {
		this.processLog = processLog;
	}

	public String getTip() {
		if (StringUtils.isEmpty(tip)) {
			return "恭喜您，保存成功！";
		}
		return tip;
	}

	public void setTip(String tip) {
		this.tip = tip;
	}

	/**
	 * 业务流程执行
	 * 
	 * @param domain
	 * @throws Exception
	 */
	protected Activity process(M domain) throws Exception {
		Activity activity = null;
		if (domain instanceof IWorkflowProcessable && !StringUtils.isEmpty(this.processLog.getOperateOpinion())) {// 流程对象，则实例化流程日志
			activity = SimpleWorkflow.execute(this, (IWorkflowProcessable) domain);
			IWorkflowProcessable process = (IWorkflowProcessable) domain;
			if (process.getParticipator() != null) {
				this.tip = "操作成功!";
				this.tip += "请等待【" + process.getParticipator().getName() + "】的处理！";
			}
		}
		return activity;
	}

	/**
	 * 记录流程日志
	 * 
	 * @param activity
	 * @param domain
	 * @throws Exception
	 */
	protected void logprocess(Activity activity, M domain) throws Exception {
		if (domain instanceof IWorkflowProcessable //
				&& !StringUtils.isEmpty(this.processLog.getOperateOpinion()) //
				&& activity != null) {// 保存流程日志
			this.processLog.setDomain(domain);// 业务对象
			this.processLog.setOperateTime(new Date());// 操作时间
			this.processLog.setOperator(getCurrentUser());// 操作人
			this.processLog.setOperateStep(activity.getName());// 操作阶段
			new ProcessLogDao().save(this.processLog);
		}
	}
}
